#include "pbirsm.hpp"
#ifndef __SYNTHESIS__ // 仅在 C 仿真时包含 iostream
#include <iostream>
#include <iomanip> // For std::fixed, std::setprecision
#endif

// -----------------------------------------------------------
// PBIRSM (Parameter Buffer Interface and Raster Setup Module) 模块实现
// 职责：从DDR读取三角形参数，并流式输出给HR模块
// -----------------------------------------------------------
void parameter_buffer_interface_and_raster_setup(
    ddr_word_t* params_buffer_base_addr, // 指向DDR中三角形参数缓冲区的 64 位 AXI Master
    hls::stream<raster_params_packet_fixed>& output_raster_params_stream, // 输出到HR模块的三角形参数流
    const ap_uint<16> num_triangles_to_process // 本帧需要处理的三角形数量，由PS写入
) {
    #pragma HLS INTERFACE s_axilite port=params_buffer_base_addr bundle=ctrl_s_axilite
    #pragma HLS INTERFACE s_axilite port=num_triangles_to_process bundle=ctrl_s_axilite
    #pragma HLS INTERFACE s_axilite port=return bundle=ctrl_s_axilite

    // 提高 AXI 参数，匹配 DDR 访问
    // MODIFIED: 计算深度：MAX_NUM_TRIANGLES (511) * NUM_AXI_WORDS_PER_PACKET (23) = 11753 words
    #pragma HLS INTERFACE m_axi port=params_buffer_base_addr offset=slave bundle=m_axi_gmem_params_read max_read_burst_length=256 latency=60 num_read_outstanding=16 num_write_outstanding=16 depth=11753
    #pragma HLS INTERFACE axis port=output_raster_params_stream

#ifndef __SYNTHESIS__ // Debug: Print PBIRSM start message
    std::cout << "[PBIRSM DEBUG] Starting to read " << num_triangles_to_process << " triangles from DDR." << std::endl;
#endif

    TRIANGLE_READ_LOOP:
    // LOOP_TRIPCOUNT min=1 max=MAX_NUM_TRIANGLES 将根据 hr_tbr.hpp 中的新定义 (511) 自动更新
    for (ap_uint<16> triangle_idx = 0; triangle_idx < num_triangles_to_process; ++triangle_idx) {
        #pragma HLS LOOP_TRIPCOUNT min=1 max=MAX_NUM_TRIANGLES
        #pragma HLS PIPELINE

        // 计算当前三角形的起始 DDR 字地址偏移
        ap_uint<32> current_word_offset = triangle_idx * NUM_AXI_WORDS_PER_PACKET; 

        raster_params_packet_fixed current_triangle_params;
        
        // 直接从 DDR 读取每个字段，每个字段占用一个 64 位 DDR 字
        // HLS 会将这些独立的读取优化为 AXI Burst Read。
        
        // v0_x, v0_y, v1_x, v1_y, v2_x, v2_y (6 * fp_coord_t = 6 * 64 = 6 words)
        current_triangle_params.v0_x = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.v0_y = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.v1_x = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.v1_y = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.v2_x = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.v2_y = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);

        // v0_z, v1_z, v2_z (3 * fp_z_buffer_t = 3 * 16 = 3 words)
        // 从 64 位 DDR 字中提取低 16 位
        current_triangle_params.v0_z = (ap_uint<16>)params_buffer_base_addr[current_word_offset++];
        current_triangle_params.v1_z = (ap_uint<16>)params_buffer_base_addr[current_word_offset++];
        current_triangle_params.v2_z = (ap_uint<16>)params_buffer_base_addr[current_word_offset++];

        // edge0_A, B, C; edge1_A, B, C; edge2_A, B, C (9 * fp_coord_t = 9 * 64 = 9 words)
        current_triangle_params.edge0_A = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge0_B = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge0_C = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge1_A = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge1_B = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge1_C = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge2_A = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge2_B = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.edge2_C = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);

        // dzdx, dzdy (2 * fp_coord_t = 2 * 64 = 2 words)
        current_triangle_params.dzdx = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);
        current_triangle_params.dzdy = fpal::to_fp_coord_from_long_long(params_buffer_base_addr[current_word_offset++]);

        // pure_color_R, G, B (3 * fp_color_channel_t = 3 * 8 = 3 words)
        // 从 64 位 DDR 字中提取低 8 位
        current_triangle_params.pure_color_R = (ap_uint<8>)params_buffer_base_addr[current_word_offset++];
        current_triangle_params.pure_color_G = (ap_uint<8>)params_buffer_base_addr[current_word_offset++];
        current_triangle_params.pure_color_B = (ap_uint<8>)params_buffer_base_addr[current_word_offset++];

        output_raster_params_stream.write(current_triangle_params);
    }
#ifndef __SYNTHESIS__ // Debug: Print PBIRSM finish message
    std::cout << "[PBIRSM DEBUG] Finished reading all triangles." << std::endl;
#endif
}

